/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.plc4x.java.bacnetip.readwrite;

import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
import static org.apache.plc4x.java.spi.generation.StaticHelper.*;

import java.time.*;
import java.util.*;
import org.apache.plc4x.java.api.exceptions.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.spi.codegen.*;
import org.apache.plc4x.java.spi.codegen.fields.*;
import org.apache.plc4x.java.spi.codegen.io.*;
import org.apache.plc4x.java.spi.generation.*;

// Code generated by code-generation. DO NOT EDIT.

public class BACnetEventParameterExtendedParameters implements Message {

  // Properties.
  protected final BACnetOpeningTag openingTag;
  protected final BACnetTagHeader peekedTagHeader;
  protected final BACnetApplicationTagNull nullValue;
  protected final BACnetApplicationTagReal realValue;
  protected final BACnetApplicationTagUnsignedInteger unsignedValue;
  protected final BACnetApplicationTagBoolean booleanValue;
  protected final BACnetApplicationTagSignedInteger integerValue;
  protected final BACnetApplicationTagDouble doubleValue;
  protected final BACnetApplicationTagOctetString octetStringValue;
  protected final BACnetApplicationTagCharacterString characterStringValue;
  protected final BACnetApplicationTagBitString bitStringValue;
  protected final BACnetApplicationTagEnumerated enumeratedValue;
  protected final BACnetApplicationTagDate dateValue;
  protected final BACnetApplicationTagTime timeValue;
  protected final BACnetApplicationTagObjectIdentifier objectIdentifier;
  protected final BACnetDeviceObjectPropertyReferenceEnclosed reference;
  protected final BACnetClosingTag closingTag;

  public BACnetEventParameterExtendedParameters(
      BACnetOpeningTag openingTag,
      BACnetTagHeader peekedTagHeader,
      BACnetApplicationTagNull nullValue,
      BACnetApplicationTagReal realValue,
      BACnetApplicationTagUnsignedInteger unsignedValue,
      BACnetApplicationTagBoolean booleanValue,
      BACnetApplicationTagSignedInteger integerValue,
      BACnetApplicationTagDouble doubleValue,
      BACnetApplicationTagOctetString octetStringValue,
      BACnetApplicationTagCharacterString characterStringValue,
      BACnetApplicationTagBitString bitStringValue,
      BACnetApplicationTagEnumerated enumeratedValue,
      BACnetApplicationTagDate dateValue,
      BACnetApplicationTagTime timeValue,
      BACnetApplicationTagObjectIdentifier objectIdentifier,
      BACnetDeviceObjectPropertyReferenceEnclosed reference,
      BACnetClosingTag closingTag) {
    super();
    this.openingTag = openingTag;
    this.peekedTagHeader = peekedTagHeader;
    this.nullValue = nullValue;
    this.realValue = realValue;
    this.unsignedValue = unsignedValue;
    this.booleanValue = booleanValue;
    this.integerValue = integerValue;
    this.doubleValue = doubleValue;
    this.octetStringValue = octetStringValue;
    this.characterStringValue = characterStringValue;
    this.bitStringValue = bitStringValue;
    this.enumeratedValue = enumeratedValue;
    this.dateValue = dateValue;
    this.timeValue = timeValue;
    this.objectIdentifier = objectIdentifier;
    this.reference = reference;
    this.closingTag = closingTag;
  }

  public BACnetOpeningTag getOpeningTag() {
    return openingTag;
  }

  public BACnetTagHeader getPeekedTagHeader() {
    return peekedTagHeader;
  }

  public BACnetApplicationTagNull getNullValue() {
    return nullValue;
  }

  public BACnetApplicationTagReal getRealValue() {
    return realValue;
  }

  public BACnetApplicationTagUnsignedInteger getUnsignedValue() {
    return unsignedValue;
  }

  public BACnetApplicationTagBoolean getBooleanValue() {
    return booleanValue;
  }

  public BACnetApplicationTagSignedInteger getIntegerValue() {
    return integerValue;
  }

  public BACnetApplicationTagDouble getDoubleValue() {
    return doubleValue;
  }

  public BACnetApplicationTagOctetString getOctetStringValue() {
    return octetStringValue;
  }

  public BACnetApplicationTagCharacterString getCharacterStringValue() {
    return characterStringValue;
  }

  public BACnetApplicationTagBitString getBitStringValue() {
    return bitStringValue;
  }

  public BACnetApplicationTagEnumerated getEnumeratedValue() {
    return enumeratedValue;
  }

  public BACnetApplicationTagDate getDateValue() {
    return dateValue;
  }

  public BACnetApplicationTagTime getTimeValue() {
    return timeValue;
  }

  public BACnetApplicationTagObjectIdentifier getObjectIdentifier() {
    return objectIdentifier;
  }

  public BACnetDeviceObjectPropertyReferenceEnclosed getReference() {
    return reference;
  }

  public BACnetClosingTag getClosingTag() {
    return closingTag;
  }

  public short getPeekedTagNumber() {
    return (short) (getPeekedTagHeader().getActualTagNumber());
  }

  public boolean getIsOpeningTag() {
    return (boolean) ((getPeekedTagHeader().getLengthValueType()) == (0x6));
  }

  public boolean getIsClosingTag() {
    return (boolean) ((getPeekedTagHeader().getLengthValueType()) == (0x7));
  }

  public void serialize(WriteBuffer writeBuffer) throws SerializationException {
    PositionAware positionAware = writeBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
    writeBuffer.pushContext("BACnetEventParameterExtendedParameters");

    // Simple Field (openingTag)
    writeSimpleField("openingTag", openingTag, writeComplex(writeBuffer));

    // Virtual field (doesn't serialize anything, just makes the value available)
    short peekedTagNumber = getPeekedTagNumber();
    writeBuffer.writeVirtual("peekedTagNumber", peekedTagNumber);

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isOpeningTag = getIsOpeningTag();
    writeBuffer.writeVirtual("isOpeningTag", isOpeningTag);

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isClosingTag = getIsClosingTag();
    writeBuffer.writeVirtual("isClosingTag", isClosingTag);

    // Optional Field (nullValue) (Can be skipped, if the value is null)
    writeOptionalField("nullValue", nullValue, writeComplex(writeBuffer));

    // Optional Field (realValue) (Can be skipped, if the value is null)
    writeOptionalField("realValue", realValue, writeComplex(writeBuffer));

    // Optional Field (unsignedValue) (Can be skipped, if the value is null)
    writeOptionalField("unsignedValue", unsignedValue, writeComplex(writeBuffer));

    // Optional Field (booleanValue) (Can be skipped, if the value is null)
    writeOptionalField("booleanValue", booleanValue, writeComplex(writeBuffer));

    // Optional Field (integerValue) (Can be skipped, if the value is null)
    writeOptionalField("integerValue", integerValue, writeComplex(writeBuffer));

    // Optional Field (doubleValue) (Can be skipped, if the value is null)
    writeOptionalField("doubleValue", doubleValue, writeComplex(writeBuffer));

    // Optional Field (octetStringValue) (Can be skipped, if the value is null)
    writeOptionalField("octetStringValue", octetStringValue, writeComplex(writeBuffer));

    // Optional Field (characterStringValue) (Can be skipped, if the value is null)
    writeOptionalField("characterStringValue", characterStringValue, writeComplex(writeBuffer));

    // Optional Field (bitStringValue) (Can be skipped, if the value is null)
    writeOptionalField("bitStringValue", bitStringValue, writeComplex(writeBuffer));

    // Optional Field (enumeratedValue) (Can be skipped, if the value is null)
    writeOptionalField("enumeratedValue", enumeratedValue, writeComplex(writeBuffer));

    // Optional Field (dateValue) (Can be skipped, if the value is null)
    writeOptionalField("dateValue", dateValue, writeComplex(writeBuffer));

    // Optional Field (timeValue) (Can be skipped, if the value is null)
    writeOptionalField("timeValue", timeValue, writeComplex(writeBuffer));

    // Optional Field (objectIdentifier) (Can be skipped, if the value is null)
    writeOptionalField("objectIdentifier", objectIdentifier, writeComplex(writeBuffer));

    // Optional Field (reference) (Can be skipped, if the value is null)
    writeOptionalField("reference", reference, writeComplex(writeBuffer));

    // Simple Field (closingTag)
    writeSimpleField("closingTag", closingTag, writeComplex(writeBuffer));

    writeBuffer.popContext("BACnetEventParameterExtendedParameters");
  }

  @Override
  public int getLengthInBytes() {
    return (int) Math.ceil((float) getLengthInBits() / 8.0);
  }

  @Override
  public int getLengthInBits() {
    int lengthInBits = 0;
    BACnetEventParameterExtendedParameters _value = this;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    // Simple field (openingTag)
    lengthInBits += openingTag.getLengthInBits();

    // A virtual field doesn't have any in- or output.

    // A virtual field doesn't have any in- or output.

    // A virtual field doesn't have any in- or output.

    // Optional Field (nullValue)
    if (nullValue != null) {
      lengthInBits += nullValue.getLengthInBits();
    }

    // Optional Field (realValue)
    if (realValue != null) {
      lengthInBits += realValue.getLengthInBits();
    }

    // Optional Field (unsignedValue)
    if (unsignedValue != null) {
      lengthInBits += unsignedValue.getLengthInBits();
    }

    // Optional Field (booleanValue)
    if (booleanValue != null) {
      lengthInBits += booleanValue.getLengthInBits();
    }

    // Optional Field (integerValue)
    if (integerValue != null) {
      lengthInBits += integerValue.getLengthInBits();
    }

    // Optional Field (doubleValue)
    if (doubleValue != null) {
      lengthInBits += doubleValue.getLengthInBits();
    }

    // Optional Field (octetStringValue)
    if (octetStringValue != null) {
      lengthInBits += octetStringValue.getLengthInBits();
    }

    // Optional Field (characterStringValue)
    if (characterStringValue != null) {
      lengthInBits += characterStringValue.getLengthInBits();
    }

    // Optional Field (bitStringValue)
    if (bitStringValue != null) {
      lengthInBits += bitStringValue.getLengthInBits();
    }

    // Optional Field (enumeratedValue)
    if (enumeratedValue != null) {
      lengthInBits += enumeratedValue.getLengthInBits();
    }

    // Optional Field (dateValue)
    if (dateValue != null) {
      lengthInBits += dateValue.getLengthInBits();
    }

    // Optional Field (timeValue)
    if (timeValue != null) {
      lengthInBits += timeValue.getLengthInBits();
    }

    // Optional Field (objectIdentifier)
    if (objectIdentifier != null) {
      lengthInBits += objectIdentifier.getLengthInBits();
    }

    // Optional Field (reference)
    if (reference != null) {
      lengthInBits += reference.getLengthInBits();
    }

    // Simple field (closingTag)
    lengthInBits += closingTag.getLengthInBits();

    return lengthInBits;
  }

  public static BACnetEventParameterExtendedParameters staticParse(
      ReadBuffer readBuffer, Short tagNumber) throws ParseException {
    readBuffer.pullContext("BACnetEventParameterExtendedParameters");
    PositionAware positionAware = readBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    BACnetOpeningTag openingTag =
        readSimpleField(
            "openingTag",
            readComplex(
                () -> BACnetOpeningTag.staticParse(readBuffer, (short) (tagNumber)), readBuffer));

    BACnetTagHeader peekedTagHeader =
        readPeekField(
            "peekedTagHeader",
            readComplex(() -> BACnetTagHeader.staticParse(readBuffer), readBuffer));
    short peekedTagNumber =
        readVirtualField("peekedTagNumber", short.class, peekedTagHeader.getActualTagNumber());
    boolean isOpeningTag =
        readVirtualField(
            "isOpeningTag", boolean.class, (peekedTagHeader.getLengthValueType()) == (0x6));
    boolean isClosingTag =
        readVirtualField(
            "isClosingTag", boolean.class, (peekedTagHeader.getLengthValueType()) == (0x7));

    BACnetApplicationTagNull nullValue =
        readOptionalField(
            "nullValue",
            readComplex(
                () -> (BACnetApplicationTagNull) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x0)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagReal realValue =
        readOptionalField(
            "realValue",
            readComplex(
                () -> (BACnetApplicationTagReal) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x4)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagUnsignedInteger unsignedValue =
        readOptionalField(
            "unsignedValue",
            readComplex(
                () ->
                    (BACnetApplicationTagUnsignedInteger)
                        BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x2)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagBoolean booleanValue =
        readOptionalField(
            "booleanValue",
            readComplex(
                () -> (BACnetApplicationTagBoolean) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x1)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagSignedInteger integerValue =
        readOptionalField(
            "integerValue",
            readComplex(
                () ->
                    (BACnetApplicationTagSignedInteger)
                        BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x3)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagDouble doubleValue =
        readOptionalField(
            "doubleValue",
            readComplex(
                () -> (BACnetApplicationTagDouble) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x5)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagOctetString octetStringValue =
        readOptionalField(
            "octetStringValue",
            readComplex(
                () ->
                    (BACnetApplicationTagOctetString) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x6)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagCharacterString characterStringValue =
        readOptionalField(
            "characterStringValue",
            readComplex(
                () ->
                    (BACnetApplicationTagCharacterString)
                        BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x7)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagBitString bitStringValue =
        readOptionalField(
            "bitStringValue",
            readComplex(
                () -> (BACnetApplicationTagBitString) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x8)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagEnumerated enumeratedValue =
        readOptionalField(
            "enumeratedValue",
            readComplex(
                () -> (BACnetApplicationTagEnumerated) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0x9)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagDate dateValue =
        readOptionalField(
            "dateValue",
            readComplex(
                () -> (BACnetApplicationTagDate) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0xA)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagTime timeValue =
        readOptionalField(
            "timeValue",
            readComplex(
                () -> (BACnetApplicationTagTime) BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            (((peekedTagNumber) == (0xB)) && (!(isOpeningTag))) && (!(isClosingTag)));

    BACnetApplicationTagObjectIdentifier objectIdentifier =
        readOptionalField(
            "objectIdentifier",
            readComplex(
                () ->
                    (BACnetApplicationTagObjectIdentifier)
                        BACnetApplicationTag.staticParse(readBuffer),
                readBuffer),
            ((peekedTagNumber) == (0xC)) && (!(isOpeningTag)));

    BACnetDeviceObjectPropertyReferenceEnclosed reference =
        readOptionalField(
            "reference",
            readComplex(
                () ->
                    BACnetDeviceObjectPropertyReferenceEnclosed.staticParse(
                        readBuffer, (short) (0)),
                readBuffer),
            (isOpeningTag) && (!(isClosingTag)));

    BACnetClosingTag closingTag =
        readSimpleField(
            "closingTag",
            readComplex(
                () -> BACnetClosingTag.staticParse(readBuffer, (short) (tagNumber)), readBuffer));

    readBuffer.closeContext("BACnetEventParameterExtendedParameters");
    // Create the instance
    BACnetEventParameterExtendedParameters _bACnetEventParameterExtendedParameters;
    _bACnetEventParameterExtendedParameters =
        new BACnetEventParameterExtendedParameters(
            openingTag,
            peekedTagHeader,
            nullValue,
            realValue,
            unsignedValue,
            booleanValue,
            integerValue,
            doubleValue,
            octetStringValue,
            characterStringValue,
            bitStringValue,
            enumeratedValue,
            dateValue,
            timeValue,
            objectIdentifier,
            reference,
            closingTag);
    return _bACnetEventParameterExtendedParameters;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof BACnetEventParameterExtendedParameters)) {
      return false;
    }
    BACnetEventParameterExtendedParameters that = (BACnetEventParameterExtendedParameters) o;
    return (getOpeningTag() == that.getOpeningTag())
        && (getPeekedTagHeader() == that.getPeekedTagHeader())
        && (getNullValue() == that.getNullValue())
        && (getRealValue() == that.getRealValue())
        && (getUnsignedValue() == that.getUnsignedValue())
        && (getBooleanValue() == that.getBooleanValue())
        && (getIntegerValue() == that.getIntegerValue())
        && (getDoubleValue() == that.getDoubleValue())
        && (getOctetStringValue() == that.getOctetStringValue())
        && (getCharacterStringValue() == that.getCharacterStringValue())
        && (getBitStringValue() == that.getBitStringValue())
        && (getEnumeratedValue() == that.getEnumeratedValue())
        && (getDateValue() == that.getDateValue())
        && (getTimeValue() == that.getTimeValue())
        && (getObjectIdentifier() == that.getObjectIdentifier())
        && (getReference() == that.getReference())
        && (getClosingTag() == that.getClosingTag())
        && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        getOpeningTag(),
        getPeekedTagHeader(),
        getNullValue(),
        getRealValue(),
        getUnsignedValue(),
        getBooleanValue(),
        getIntegerValue(),
        getDoubleValue(),
        getOctetStringValue(),
        getCharacterStringValue(),
        getBitStringValue(),
        getEnumeratedValue(),
        getDateValue(),
        getTimeValue(),
        getObjectIdentifier(),
        getReference(),
        getClosingTag());
  }

  @Override
  public String toString() {
    WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true);
    try {
      writeBufferBoxBased.writeSerializable(this);
    } catch (SerializationException e) {
      throw new RuntimeException(e);
    }
    return "\n" + writeBufferBoxBased.getBox().toString() + "\n";
  }
}
